
#include "InputLine.h"

// Delimiters for string tokenizing 
const string InputLine::DELIMITERS = " ()[]{};<>=+-*&"; 

//*****************************************************************************
//Constructor from Parser object
//*****************************************************************************
InputLine::InputLine(const Parser& prs):
	parser(prs)
{
}

//*****************************************************************************
//copy CTOR
//*****************************************************************************
InputLine::InputLine(const InputLine& inp):
	parser(inp.parser)
{
	fileTokens = inp.fileTokens;
}

//*****************************************************************************
//assignment operator
//*****************************************************************************
const InputLine& InputLine::operator=(const InputLine& inp)
{
	if (this != &inp)
	{
		fileTokens = inp.fileTokens;
		parser = inp.parser;
	}

	return *this;
}

//*****************************************************************************
//divide file lines into tokens and put them into vector container
//*****************************************************************************
void InputLine::tokenizeFile()
{
	vector<string>::iterator it;
	vector<string> vct = Parser(parser).getLineContainer();
	it = vct.begin();
	while (it != vct.end())
	{
		fileTokens.push_back(tokenizeLine(*it++));
	}

}


//*****************************************************************************
//divide line into tokens and put them into vector
//*****************************************************************************
const vector<string> InputLine::tokenizeLine(const string& str)
{
	vector<string> lineTokens;
    // Begin from zero position.
    string::size_type lastPos = 0;
    
	// Find first "non-DELIMITER".
    string::size_type pos     = str.find_first_of(DELIMITERS, lastPos);
	// if no delimiters in line, bush whole line into the token container
	if (pos == string::npos) lineTokens.push_back(str);
	// help variable
	string::size_type tmp;

    while (string::npos != pos)
    {
        // Find token, add it to the vector.
		if (lastPos != pos) // else the DELIMETER is the token
			lineTokens.push_back(str.substr(lastPos, pos - lastPos));
		
		// Add the DELIMITER (except ' ') to the vector.
		if (str[pos] != ' ')
			if(((str[pos]=='=')&&(str[pos+1]=='=')) || ((str[pos]=='+')&&(str[pos+1]=='+'))
				|| ((str[pos]=='-')&&(str[pos+1]=='-')) || ((str[pos]=='<')&&(str[pos+1]=='<')) || 
				((str[pos]=='>')&&(str[pos+1]=='>')) || ((str[pos]=='-')&&(str[pos+1]=='>')))
			{
				lineTokens.push_back(str.substr(pos, 2));
				pos++;
			}
			else
				lineTokens.push_back(str.substr(pos, 1));
        
		// Skip the DELIMITER.
		if (pos < (str.length()-1))
			lastPos = pos+1;
		else 
			break;
        
		// Find next "non-DELIMITER"
		tmp = pos;
        pos = str.find_first_of(DELIMITERS, lastPos);

		// last token
		if (pos == string::npos)
			lineTokens.push_back(str.substr(lastPos, tmp - lastPos));
    }

	return lineTokens;
}

//*****************************************************************************
// Print out tokens of whole file
//*****************************************************************************
void InputLine::printOutFileTokens() const
{
	vector<vector<string>>::const_iterator extIt;
	vector<string>::const_iterator intIt;

	extIt = fileTokens.begin();

	while (extIt != fileTokens.end())
	{
		intIt = (*extIt).begin();

		while (intIt != (*extIt).end())
		{
			cout << *intIt++ << ' ';
		}

		cout << endl;
		extIt++;
	}
}

//*****************************************************************************
//get reference to container of file tokens
//*****************************************************************************
const vector<vector<string>>& InputLine::getFileTokens() const
{
	return fileTokens;
}

//*****************************************************************************
//get number of tokens in line
//*****************************************************************************
int InputLine::getNumOfTokensInLine(int line) const
{
	if (line<0 || line>parser.getNumOfLines())
	{
		cout << "error: no such line in file" << endl;
		return -1;
	}

	return  (int) (fileTokens[line-1]).size();
}

//*****************************************************************************
// Get number of tokens in file
//*****************************************************************************
int InputLine::getNumOfTokensInFile() const
{
	int counter=0;

	vector<vector<string>>::const_iterator extIt;
	vector<string>::const_iterator intIt;

	extIt = fileTokens.begin();

	while (extIt != fileTokens.end())
	{
		intIt = (*extIt).begin();

		while (intIt != (*extIt).end())
		{
			counter++;
			intIt++;
		}

		extIt++;
	}

	return counter;
}


//*****************************************************************************
// DTOR
//*****************************************************************************
InputLine::~InputLine(void)
{
}
